/**
 * LeaderboardSystem - 排行榜系统
 * 管理本地排行榜和分数记录功能
 */

import type { LeaderboardEntry } from './StorageManager'

/**
 * 排行榜类型枚举
 */
export enum LeaderboardType {
  HIGH_SCORE = 'high_score',
  LONGEST_DISTANCE = 'longest_distance',
  MOST_COINS = 'most_coins',
  SURVIVAL_TIME = 'survival_time',
  WEEKLY = 'weekly',
  MONTHLY = 'monthly',
  ALL_TIME = 'all_time'
}

/**
 * 排行榜配置接口
 */
export interface LeaderboardConfig {
  maxEntries: number
  sortBy: 'score' | 'distance' | 'coins' | 'survivalTime'
  sortOrder: 'desc' | 'asc'
  timeWindow?: number // 时间窗口（毫秒）
}

/**
 * 游戏记录接口
 */
export interface GameRecord {
  id: string
  playerName: string
  score: number
  distance: number
  coins: number
  survivalTime: number
  character: string
  date: Date
  achievements: number
  powerUpsUsed: string[]
  gameMode: string
  difficulty: string
}

/**
 * 排行榜统计信息
 */
export interface LeaderboardStats {
  totalEntries: number
  averageScore: number
  averageDistance: number
  topScore: number
  topDistance: number
  mostActivePlayer: string
  mostUsedCharacter: string
  averageGameTime: number
}

/**
 * 排行榜系统类
 */
export class LeaderboardSystem {
  private leaderboards: Map<LeaderboardType, LeaderboardEntry[]> = new Map()
  private gameRecords: GameRecord[] = []
  private configs: Map<LeaderboardType, LeaderboardConfig> = new Map()

  constructor() {
    this.initializeLeaderboards()
  }

  /**
   * 初始化排行榜配置
   */
  private initializeLeaderboards(): void {
    // 高分排行榜
    this.configs.set(LeaderboardType.HIGH_SCORE, {
      maxEntries: 10,
      sortBy: 'score',
      sortOrder: 'desc'
    })

    // 最远距离排行榜
    this.configs.set(LeaderboardType.LONGEST_DISTANCE, {
      maxEntries: 10,
      sortBy: 'distance',
      sortOrder: 'desc'
    })

    // 金币收集排行榜
    this.configs.set(LeaderboardType.MOST_COINS, {
      maxEntries: 10,
      sortBy: 'coins',
      sortOrder: 'desc'
    })

    // 生存时间排行榜
    this.configs.set(LeaderboardType.SURVIVAL_TIME, {
      maxEntries: 10,
      sortBy: 'survivalTime',
      sortOrder: 'desc'
    })

    // 周排行榜
    this.configs.set(LeaderboardType.WEEKLY, {
      maxEntries: 20,
      sortBy: 'score',
      sortOrder: 'desc',
      timeWindow: 7 * 24 * 60 * 60 * 1000 // 7天
    })

    // 月排行榜
    this.configs.set(LeaderboardType.MONTHLY, {
      maxEntries: 50,
      sortBy: 'score',
      sortOrder: 'desc',
      timeWindow: 30 * 24 * 60 * 60 * 1000 // 30天
    })

    // 全时排行榜
    this.configs.set(LeaderboardType.ALL_TIME, {
      maxEntries: 100,
      sortBy: 'score',
      sortOrder: 'desc'
    })

    // 初始化空排行榜
    this.configs.forEach((config, type) => {
      this.leaderboards.set(type, [])
    })
  }

  /**
   * 添加游戏记录
   */
  addGameRecord(record: Omit<GameRecord, 'id' | 'date'>): GameRecord {
    const gameRecord: GameRecord = {
      ...record,
      id: this.generateRecordId(),
      date: new Date()
    }

    this.gameRecords.push(gameRecord)
    this.updateLeaderboards(gameRecord)
    
    return gameRecord
  }

  /**
   * 生成记录ID
   */
  private generateRecordId(): string {
    return `record_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }

  /**
   * 更新所有排行榜
   */
  private updateLeaderboards(record: GameRecord): void {
    this.configs.forEach((config, type) => {
      this.updateLeaderboard(type, record, config)
    })
  }

  /**
   * 更新特定排行榜
   */
  private updateLeaderboard(type: LeaderboardType, record: GameRecord, config: LeaderboardConfig): void {
    const leaderboard = this.leaderboards.get(type) || []
    
    // 检查时间窗口
    if (config.timeWindow) {
      const cutoffTime = new Date(Date.now() - config.timeWindow)
      if (record.date < cutoffTime) {
        return // 记录太旧，不添加到时间限制的排行榜
      }
    }

    // 创建排行榜条目
    const entry: LeaderboardEntry = {
      id: record.id,
      playerName: record.playerName,
      score: record.score,
      distance: record.distance,
      character: record.character,
      date: record.date,
      achievements: record.achievements
    }

    // 添加到排行榜
    leaderboard.push(entry)

    // 排序
    this.sortLeaderboard(leaderboard, config)

    // 限制条目数量
    if (leaderboard.length > config.maxEntries) {
      leaderboard.splice(config.maxEntries)
    }

    this.leaderboards.set(type, leaderboard)
  }

  /**
   * 排序排行榜
   */
  private sortLeaderboard(leaderboard: LeaderboardEntry[], config: LeaderboardConfig): void {
    leaderboard.sort((a, b) => {
      let valueA: number
      let valueB: number

      switch (config.sortBy) {
        case 'score':
          valueA = a.score
          valueB = b.score
          break
        case 'distance':
          valueA = a.distance
          valueB = b.distance
          break
        case 'coins':
          // 假设LeaderboardEntry有coins字段，或者使用score作为替代
          valueA = a.score // 临时使用score
          valueB = b.score
          break
        case 'survivalTime':
          // 假设LeaderboardEntry有survivalTime字段，或者使用distance作为替代
          valueA = a.distance // 临时使用distance
          valueB = b.distance
          break
        default:
          valueA = a.score
          valueB = b.score
      }

      if (config.sortOrder === 'desc') {
        return valueB - valueA
      } else {
        return valueA - valueB
      }
    })
  }

  /**
   * 获取排行榜
   */
  getLeaderboard(type: LeaderboardType): LeaderboardEntry[] {
    const leaderboard = this.leaderboards.get(type) || []
    
    // 如果是时间限制的排行榜，过滤过期记录
    const config = this.configs.get(type)
    if (config?.timeWindow) {
      const cutoffTime = new Date(Date.now() - config.timeWindow)
      return leaderboard.filter(entry => entry.date >= cutoffTime)
    }

    return [...leaderboard] // 返回副本
  }

  /**
   * 获取玩家在排行榜中的排名
   */
  getPlayerRank(type: LeaderboardType, playerName: string): number {
    const leaderboard = this.getLeaderboard(type)
    const index = leaderboard.findIndex(entry => entry.playerName === playerName)
    return index >= 0 ? index + 1 : -1 // 排名从1开始，-1表示未上榜
  }

  /**
   * 获取玩家的最佳记录
   */
  getPlayerBestRecord(playerName: string): GameRecord | null {
    const playerRecords = this.gameRecords.filter(record => record.playerName === playerName)
    if (playerRecords.length === 0) {
      return null
    }

    return playerRecords.reduce((best, current) => {
      return current.score > best.score ? current : best
    })
  }

  /**
   * 获取玩家的所有记录
   */
  getPlayerRecords(playerName: string, limit?: number): GameRecord[] {
    const playerRecords = this.gameRecords
      .filter(record => record.playerName === playerName)
      .sort((a, b) => b.date.getTime() - a.date.getTime()) // 按日期降序排列

    return limit ? playerRecords.slice(0, limit) : playerRecords
  }

  /**
   * 获取排行榜统计信息
   */
  getLeaderboardStats(type: LeaderboardType): LeaderboardStats {
    const leaderboard = this.getLeaderboard(type)
    
    if (leaderboard.length === 0) {
      return {
        totalEntries: 0,
        averageScore: 0,
        averageDistance: 0,
        topScore: 0,
        topDistance: 0,
        mostActivePlayer: '',
        mostUsedCharacter: '',
        averageGameTime: 0
      }
    }

    const totalScore = leaderboard.reduce((sum, entry) => sum + entry.score, 0)
    const totalDistance = leaderboard.reduce((sum, entry) => sum + entry.distance, 0)
    const topScore = Math.max(...leaderboard.map(entry => entry.score))
    const topDistance = Math.max(...leaderboard.map(entry => entry.distance))

    // 统计最活跃玩家
    const playerCounts = new Map<string, number>()
    leaderboard.forEach(entry => {
      playerCounts.set(entry.playerName, (playerCounts.get(entry.playerName) || 0) + 1)
    })
    const mostActivePlayer = Array.from(playerCounts.entries())
      .reduce((max, [player, count]) => count > max[1] ? [player, count] : max, ['', 0])[0]

    // 统计最常用角色
    const characterCounts = new Map<string, number>()
    leaderboard.forEach(entry => {
      characterCounts.set(entry.character, (characterCounts.get(entry.character) || 0) + 1)
    })
    const mostUsedCharacter = Array.from(characterCounts.entries())
      .reduce((max, [character, count]) => count > max[1] ? [character, count] : max, ['', 0])[0]

    return {
      totalEntries: leaderboard.length,
      averageScore: totalScore / leaderboard.length,
      averageDistance: totalDistance / leaderboard.length,
      topScore,
      topDistance,
      mostActivePlayer,
      mostUsedCharacter,
      averageGameTime: 0 // 需要从游戏记录中计算
    }
  }

  /**
   * 清理过期记录
   */
  cleanupExpiredRecords(): void {
    this.configs.forEach((config, type) => {
      if (config.timeWindow) {
        const cutoffTime = new Date(Date.now() - config.timeWindow)
        const leaderboard = this.leaderboards.get(type) || []
        const filteredLeaderboard = leaderboard.filter(entry => entry.date >= cutoffTime)
        this.leaderboards.set(type, filteredLeaderboard)
      }
    })

    // 清理游戏记录（保留最近1年的记录）
    const oneYearAgo = new Date(Date.now() - 365 * 24 * 60 * 60 * 1000)
    this.gameRecords = this.gameRecords.filter(record => record.date >= oneYearAgo)
  }

  /**
   * 获取今日最佳记录
   */
  getTodaysBest(): LeaderboardEntry | null {
    const today = new Date()
    today.setHours(0, 0, 0, 0)
    
    const todaysRecords = this.gameRecords.filter(record => {
      const recordDate = new Date(record.date)
      recordDate.setHours(0, 0, 0, 0)
      return recordDate.getTime() === today.getTime()
    })

    if (todaysRecords.length === 0) {
      return null
    }

    const bestRecord = todaysRecords.reduce((best, current) => {
      return current.score > best.score ? current : best
    })

    return {
      id: bestRecord.id,
      playerName: bestRecord.playerName,
      score: bestRecord.score,
      distance: bestRecord.distance,
      character: bestRecord.character,
      date: bestRecord.date,
      achievements: bestRecord.achievements
    }
  }

  /**
   * 检查是否创造新记录
   */
  checkNewRecord(record: GameRecord): {
    isNewHighScore: boolean
    isNewLongestDistance: boolean
    previousHighScore: number
    previousLongestDistance: number
  } {
    const allTimeLeaderboard = this.getLeaderboard(LeaderboardType.ALL_TIME)
    
    const previousHighScore = allTimeLeaderboard.length > 0 
      ? Math.max(...allTimeLeaderboard.map(entry => entry.score))
      : 0
    
    const previousLongestDistance = allTimeLeaderboard.length > 0
      ? Math.max(...allTimeLeaderboard.map(entry => entry.distance))
      : 0

    return {
      isNewHighScore: record.score > previousHighScore,
      isNewLongestDistance: record.distance > previousLongestDistance,
      previousHighScore,
      previousLongestDistance
    }
  }

  /**
   * 序列化排行榜数据
   */
  serialize(): any {
    const leaderboardsData: Record<string, LeaderboardEntry[]> = {}
    this.leaderboards.forEach((entries, type) => {
      leaderboardsData[type] = entries
    })

    return {
      leaderboards: leaderboardsData,
      gameRecords: this.gameRecords
    }
  }

  /**
   * 反序列化排行榜数据
   */
  deserialize(data: any): void {
    if (data.leaderboards) {
      Object.entries(data.leaderboards).forEach(([type, entries]) => {
        const leaderboardType = type as LeaderboardType
        const leaderboardEntries = (entries as any[]).map(entry => ({
          ...entry,
          date: new Date(entry.date)
        }))
        this.leaderboards.set(leaderboardType, leaderboardEntries)
      })
    }

    if (data.gameRecords && Array.isArray(data.gameRecords)) {
      this.gameRecords = data.gameRecords.map(record => ({
        ...record,
        date: new Date(record.date)
      }))
    }
  }

  /**
   * 重置所有排行榜
   */
  resetAllLeaderboards(): void {
    this.leaderboards.clear()
    this.gameRecords = []
    this.initializeLeaderboards()
  }

  /**
   * 获取排行榜配置
   */
  getLeaderboardConfig(type: LeaderboardType): LeaderboardConfig | undefined {
    return this.configs.get(type)
  }

  /**
   * 更新排行榜配置
   */
  updateLeaderboardConfig(type: LeaderboardType, config: Partial<LeaderboardConfig>): void {
    const currentConfig = this.configs.get(type)
    if (currentConfig) {
      this.configs.set(type, { ...currentConfig, ...config })
    }
  }
}